/*
 * Copyright 2010 Michael Nitsche
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.mnit.basis.daten.struktur.tabelle;

import de.mnit.basis.daten.struktur.S_Folge;
import de.mnit.basis.daten.struktur.liste.Liste;
import de.mnit.basis.daten.struktur.liste.S_Liste;
import de.mnit.basis.fehler.Fehler;


/**
 * @author Michael Nitsche
 */
public class Tabelle<T> extends A_Tabelle<T> {

	private final S_Liste<T>[] spalten;


	@SuppressWarnings("unchecked")
	public Tabelle(int breite) {
		this.spalten = new S_Liste[breite];
		for(int i=0; i<breite; i++)
			this.spalten[i]=Liste.neu();
	}


	public static <T> Tabelle<T> neu(int breite)   { return new Tabelle<T>(breite); }

	public static <T> Tabelle<T> neu(Class<T> k, int breite) {
		Tabelle<T> t=new Tabelle<T>(breite);
		return t;
	}

	public static <T> Tabelle<T> neu(S_Liste<T> liste, boolean direkt) {
		Tabelle<T> tab=new Tabelle<T>(1);
		tab.spalten[0]= direkt ? liste : liste.kopie();
		return tab;
	}


	// LESEN

	public int gBreite() {
		return this.spalten.length;
	}

	public Tabelle<T> kopie() {
		Tabelle<T> erg=Tabelle.neu(gBreite());
		for(S_Folge<T> zeile : this)
			erg.plus(zeile);
		return erg;
	}

	public String zuTextDebug() {
		StringBuilder sb=new StringBuilder();
		sb.append("\n");
		for(int y=1; y<=gLaenge(); y++) {
			sb.append("| ");
			for(int x=1; x<=gBreite(); x++) {
				if(x>1)
					sb.append(" | ");
				sb.append(this.gib(x, y));
			}
			sb.append(" |");
			if(y != gLaenge())
				sb.append("\n");
		}
		return sb.toString();
	}

	// AENDERN

	public void sortiereSo(int[] so) {
		for(S_Liste<T> spalte : this.spalten)
			spalte.sortiereSo(so);
	}

	public void plus(T... objekte) {
		Fehler.zahl.wenn_Nicht(gBreite(), objekte.length);
		int z=0;
		for(T t : objekte)
			this.spalten[z++].plus(t);
	}

	public void plus(S_Folge<? extends T> objekte) {
		Fehler.zahl.wenn_Nicht(gBreite(), objekte.gLaenge());
		int z=0;
		for(T t : objekte)
			this.spalten[z++].plus(t);
	}

	public void einfuegen(int zeile, T... objekte) {
		Fehler.zahl.wenn_Nicht(gBreite(), objekte.length);
		Fehler.zahl.wenn_Gleich(zeile,0);
		for(int i=1; i<=gBreite(); i++)
			this.spalten[i-1].plus(zeile, objekte[i-1]);
	}

	// GESCHÜTZT

	protected S_Liste<T> pGibSpalte(int spalte) {
		return this.spalten[spalte-1]; //TODO Kopie???
	}

	protected void pSetze(int spalte, int zeile, T objekt) {
		this.spalten[spalte-1].setze(zeile, objekt);
	}

	protected void pVertauschen(int zeile_a, int zeile_b) {
		for(S_Liste<T> spalte : spalten)
			spalte.vertauschen(zeile_a, zeile_b);
	}

	protected void pMinus(int pos) {
		for(S_Liste<T> spalte : this.spalten)
			spalte.minus(pos);
	}

}
